home *** CD-ROM | disk | FTP | other *** search
/ Underground / Underground CD1.iso / virii / zrodla / d / ddir.asm < prev    next >
Encoding:
Assembly Source File  |  1998-01-14  |  13.2 KB  |  441 lines

  1. ;    DDIR.ASM -- Double Column Sorted DIR Command
  2.  
  3. ;    ========
  4.  
  5. ;            (C) Copyright Charles Petzold, 1985
  6.  
  7. ;
  8.  
  9. ;            COM file format
  10.  
  11. ;
  12.  
  13.     
  14.  
  15. CSEG        Segment
  16.  
  17.  
  18.  
  19.         Assume    CS:CSEG, DS:CSEG
  20.  
  21.  
  22.  
  23.         Org    002Ch            ; Offset of Environment
  24.  
  25. Environment    Label    Byte
  26.  
  27.  
  28.  
  29.         Org    007Bh            ; Parameter for COMMAND.COM
  30.  
  31. NewParameter    Label    Byte
  32.  
  33.  
  34.  
  35.         Org    0080h            ; Parameter passed to program
  36.  
  37. OldParameter    Label    Byte    
  38.  
  39.  
  40.  
  41.         Org    0100h            ; Entry point
  42.  
  43. Entry:        Jmp    Begin
  44.  
  45.  
  46.  
  47. ;    All Data
  48.  
  49. ;    --------
  50.  
  51.  
  52.  
  53.         db    '(C) Copyright Charles Petzold, 1985'
  54.  
  55.  
  56.  
  57. DosVersMsg    db    "Needs DOS 2.0 +$"    ; Error messages
  58.  
  59. MemAllocMsg    db    "Memory Problem$"
  60.  
  61. CommandMsg    db    "COMMAND Problem$"
  62.  
  63.  
  64.  
  65. Comspec        db    "COMSPEC="        ; Search string in environment
  66.  
  67. CommandAsciiz    dd    ?            ; Eventual pointer to COMMAND 
  68.  
  69.  
  70.  
  71. ParamBlock    dw    ?            ; Parameter Block for EXEC
  72.  
  73.         dw    NewParameter,?        ; First ? must be replaced
  74.  
  75.         dw    5Ch,?            ;    with Environment segment;
  76.  
  77.         dw    6Ch,?            ;    others with this segment
  78.  
  79.  
  80.  
  81. OldInterrupt21    dd    ?            ; For vector address storage
  82.  
  83.  
  84.  
  85. BufferPtr    dw    Offset FileBuffer    ; For storing files listing
  86.  
  87. CharCounter    dw    0            ; Keeps track of characters
  88.  
  89. NowDoingFile    db    0            ; Flagged for file printed
  90.  
  91. WithinFileList    db    0            ; Flagged for file list
  92.  
  93. FileCounter    dw    0            ; Keeps track of files
  94.  
  95. LineCounter    db    0            ; For pausing at screen end
  96.  
  97.  
  98.  
  99. PauseMessage    db    6 dup (205)," Press any key to continue "
  100.  
  101.         db    6 dup (205),181 
  102.  
  103. PauseMsgEnd    Label    Byte
  104.  
  105.  
  106.  
  107. ;    Check DOS Version
  108.  
  109. ;    -----------------
  110.  
  111.  
  112.  
  113. Begin:        Mov    AH,30h            ; DOS Version function call
  114.  
  115.         Int    21h            ; Call DOS
  116.  
  117.         Cmp    AL,2            ; Check if version 2 
  118.  
  119.         Jae    DosVersOK        ; If equal or over, all OK
  120.  
  121.  
  122.  
  123.         Mov    DX,Offset DosVersMsg    ; Wrong DOS version message
  124.  
  125. ErrorExit:    Mov    AH,9            ; Set up for string write
  126.  
  127.         Int    21h            ; Call DOS for message
  128.  
  129.  
  130.  
  131.         Int    20h            ; Dishonorable discharge
  132.  
  133.  
  134.  
  135. ;    Adjust stack and un-allocate rest of memory 
  136.  
  137. ;    -------------------------------------------
  138.  
  139.  
  140.  
  141. DosVersOK:    Mov    DI,Offset FileBuffer    ; Place to save files
  142.  
  143.         Mov    CX,528 * 39        ; Allow room for 528 files
  144.  
  145.         Mov    AL,' '            ; Will clear with blanks
  146.  
  147.         Cld                ; Forward direction
  148.  
  149.         Rep    Stosb            ; Clear the area
  150.  
  151.  
  152.  
  153.         Mov     BX,(Offset FileBuffer) + (528 * 39) + 100h
  154.  
  155.                          ; New end of program
  156.  
  157.         Mov    SP,BX            ; Set the stack pointer
  158.  
  159.         Add    BX,15            ; Add 15 for rounding
  160.  
  161.         Mov    CL,4            ; Number of shifts
  162.  
  163.         Shr    BX,CL            ; Convert AX to segment
  164.  
  165.  
  166.  
  167.         Mov    AH,4Ah            ; DOS call to shrink down
  168.  
  169.         Int    21h            ;    allocated memory
  170.  
  171.  
  172.  
  173.         Mov    DX,Offset MemAllocMsg    ; Possible error message
  174.  
  175.         Jc    ErrorExit        ; Only print it if Carry set
  176.  
  177.  
  178.  
  179. ;    Search for Comspec in Environment
  180.  
  181. ;    ---------------------------------
  182.  
  183.  
  184.  
  185.         Mov    ES,[Environment]    ; Environment Segment
  186.  
  187.         Sub    DI,DI            ; Start search at beginning
  188.  
  189.         Cld                ; String increment to forward
  190.  
  191.  
  192.  
  193. TryThis:    Cmp    Byte Ptr ES:[DI],0    ; See if end of environment
  194.  
  195.         Jz    NoFindComSpec        ; If so, we have failed
  196.  
  197.         
  198.  
  199.         Push    DI            ; Save environment pointer
  200.  
  201.         Mov    SI,Offset ComSpec    ; String to search for
  202.  
  203.         Mov    CX,8            ; Characters in search string
  204.  
  205.         Repz    Cmpsb            ; Check if strings are same
  206.  
  207.         Pop    DI            ; Get back the pointer
  208.  
  209.  
  210.  
  211.         Jz    FoundComspec        ; Found string only zero flag
  212.  
  213.  
  214.  
  215.         Sub    AL,AL            ; Zero out AL
  216.  
  217.         Mov    CX,8000h        ; Set for big search
  218.  
  219.         Repnz    Scasb            ; Find the next zero in string
  220.  
  221.         Jmp    TryThis            ; And do the search from there
  222.  
  223.  
  224.  
  225. NoFindComSpec:    Mov    DX,Offset CommandMsg    ; Message for COMSPEC error
  226.  
  227.         Jmp    ErrorExit        ; Print it and exit
  228.  
  229.  
  230.  
  231. FoundComspec:    Add    DI,8            ; So points after 'COMSPEC='
  232.  
  233.         Mov    Word Ptr [CommandASCIIZ],DI    ; Save the address of
  234.  
  235.         Mov    Word Ptr [CommandASCIIZ + 2],ES    ;    COMMAND ASCIIZ
  236.  
  237.  
  238.  
  239. ;     Set up parameter block for EXEC call
  240.  
  241. ;    ------------------------------------
  242.  
  243.  
  244.  
  245.         Mov    [ParamBlock],ES        ; Segment of Environment string
  246.  
  247.         Mov    [ParamBlock + 4],CS    ; Segment of this program
  248.  
  249.         Mov    [ParamBlock + 8],CS    ;    so points to FCB's
  250.  
  251.         Mov    [ParamBlock + 12],CS    ;    and NewParameter
  252.  
  253.  
  254.  
  255. ;    Save and set Interrupt 21h vector address
  256.  
  257. ;    ----------------------------------------- 
  258.  
  259.  
  260.  
  261.         Mov    AX,3521h        ; DOS call to get Interrupt 21
  262.  
  263.         Int    21h            ;    vector address
  264.  
  265.         Mov    Word Ptr [OldInterrupt21],BX        ; Save offset
  266.  
  267.         Mov    Word Ptr [OldInterrupt21 + 2],ES    ; And segment    
  268.  
  269.  
  270.  
  271.         Mov    DX,Offset NewInterrupt21; Address of new Interrupt 21 
  272.  
  273.         Mov    AX,2521h        ; Do DOS call to
  274.  
  275.         Int    21h            ;    set the new address
  276.  
  277.  
  278.  
  279. ;    Fix up new parameter for "/C DIR" String
  280.  
  281. ;    ------------------------------------
  282.  
  283.  
  284.  
  285.         Mov    AL,[OldParameter]    ; Number of parameter chars     
  286.  
  287.         Add    AL,5            ; We'll be adding five more
  288.  
  289.         Mov    [NewParameter],AL    ; Save it
  290.  
  291.         Mov    Word Ptr [NewParameter + 1],'C/'    ; i.e. "/C"
  292.  
  293.         Mov    Word Ptr [NewParameter + 3],'ID'    ; Then "DI"    
  294.  
  295.         Mov    Byte Ptr [NewParameter + 5],'R'        ; And "R"
  296.  
  297.  
  298.  
  299. ;     Load COMMAND.COM
  300.  
  301. ;     -----------------
  302.  
  303.         
  304.  
  305.         Push    CS            ; Push this segment so we can
  306.  
  307.         Pop    ES            ;    set ES to it
  308.  
  309.         Mov    BX,Offset ParamBlock    ; ES:BX = address of block
  310.  
  311.         Lds    DX,[CommandAsciiz]    ; DS:DX = address of ASCIIZ
  312.  
  313.         Mov    AX,4B00h        ; EXEC call 4Bh, type 0
  314.  
  315.         Int    21h            ; Load command processor
  316.  
  317.  
  318.  
  319. ;     Return from COMMAND.COM
  320.  
  321. ;    -----------------------
  322.  
  323.  
  324.  
  325.         Mov    AX,CS        ; Get this segment in AX
  326.  
  327.         Mov    DS,AX        ; Set DS to it
  328.  
  329.         Mov    SS,AX        ; And SS for stack segment
  330.  
  331.         Mov    SP,(Offset FileBuffer) + (528 * 39) + 100h
  332.  
  333.                     ; Set Stack again
  334.  
  335.  
  336.  
  337.         PushF            ; Save Carry for error check 
  338.  
  339.         Push    DS        ; Save DS during next call
  340.  
  341.  
  342.  
  343.         Mov    DX,Word Ptr [OldInterrupt21]    ; Old Int 21 offset
  344.  
  345.         Mov    DS,Word Ptr [OldInterrupt21 + 2]; and segment
  346.  
  347.         Mov    AX,2521h        ; Call DOS to set vector
  348.  
  349.         Int    21h            ;    address to original    
  350.  
  351.  
  352.  
  353.         Pop    DS            ; Restore DS to this segment
  354.  
  355.         PopF                ; Get back Carry flage
  356.  
  357.  
  358.  
  359.         Jnc    NormalEnd        ; Continue if no error
  360.  
  361.  
  362.  
  363.         Mov    DX,Offset CommandMsg    ; Otherwise we'll print error
  364.  
  365.         Jmp    ErrorExit        ;    message and exit
  366.  
  367.  
  368.  
  369. NormalEnd:    Int    20h            ; Terminate program
  370.  
  371.  
  372.  
  373. ;    New Interrupt 21h
  374.  
  375. ;    -----------------
  376.  
  377.  
  378.  
  379. NewInterrupt21    Proc    Far
  380.  
  381.  
  382.  
  383.         Sti                ; Allow further interrupts
  384.  
  385.         Cmp    AH,40h            ; Check if file / device write
  386.  
  387.         Je    CheckHandle        ; If so, continue checks
  388.  
  389.  
  390.  
  391. SkipIntercept:    Jmp    CS:[OldInterrupt21]    ; Just jump to old interrupt
  392.  
  393.  
  394.  
  395. CheckHandle:    Cmp    BX,1            ; Check if standard output
  396.  
  397.         Jne    SkipIntercept        ; Not interested if not
  398.  
  399.  
  400.  
  401.         PushF                ; Push all registers that
  402.  
  403.         Push    AX            ;    we'll be messing with
  404.  
  405.         Push    CX
  406.  
  407.         Push    SI
  408.  
  409.         Push    DI
  410.  
  411.         Push    ES
  412.  
  413.  
  414.  
  415.         Push    CS            ; Push the code segment
  416.  
  417.         Pop    ES            ; So we can set ES to it
  418.  
  419.         Cld                ; Forward for string transfers
  420.  
  421.         Mov    SI,DX            ; Now DS:SI = text source
  422.  
  423.         Mov    DI,CS:[BufferPtr]    ; And ES:DI = text destination
  424.  
  425.  
  426.  
  427.         Cmp    CX,2            ; See if two chars to write
  428.  
  429.         Jne    RegularChars        ; If not, can't be CR/LF
  430.  
  431.  
  432.  
  433.         Cmp    Word Ptr DS:[SI],0A0Dh    ; See if CR/LF being written
  434.  
  435.         Jne    RegularChars        ; Skip rest if not CR/LF
  436.  
  437.  
  438.  
  439.         Mov    CX,CS:[CharCounter]    ; Get characters in line
  440.  
  441.         Mov    CS:[CharCounter],0    ; Start at new line
  442.  
  443.         Cmp    CS:[NowDoingFile],1    ; See if CR/LF terminates file
  444.  
  445.         Jnz    AllowTransfer        ; If not, just write to screen
  446.  
  447.  
  448.  
  449.         Mov    AX,39            ; Max characters per line
  450.  
  451.         Sub    AX,CX            ; Subtract those passed 
  452.  
  453.         Add    CS:[BufferPtr],AX    ; Kick up pointer by that
  454.  
  455.         Mov    CS:[NowDoingFile],0    ; Finished with file
  456.  
  457.         Jmp    PopAndReturn        ; So just return to COMMAND
  458.  
  459.  
  460.  
  461. RegularChars:    Add    CS:[CharCounter],CX    ; Kick up counter by number
  462.  
  463.         Cmp    CS:[CharCounter],CX    ; See if beginning of line
  464.  
  465.         Jne    NotLineBegin        ; If not, must be in middle
  466.  
  467.  
  468.  
  469.         Cmp    Byte Ptr DS:[SI],' '    ; See if first char is blank
  470.  
  471.         Jne    ItsAFile        ; If not, it's a file line
  472.  
  473.  
  474.  
  475.         Cmp    CS:[WithinFileList],1    ; See if doing file listing
  476.  
  477.         Jne    AllowTransfer        ; If not, just print stuff
  478.  
  479.  
  480.  
  481.         Call    SortAndList        ; Files done -- sort and list
  482.  
  483.         Mov    CS:[WithinFileList],0    ; Not doing files now
  484.  
  485.         Jmp    Short AllowTransfer    ; So just print the stuff
  486.  
  487.  
  488.  
  489. ItsAFile:    Cmp    CS:[FileCounter],528    ; See if 11 buffer filled up
  490.  
  491.         Jb    NotTooManyFiles        ; If not just continue
  492.  
  493.  
  494.  
  495.         Push    CX            ; Otherwise, save this register
  496.  
  497.         Call    SortAndList        ; Print all up to now
  498.  
  499.         Mov    CS:[FileCounter],0    ; Reset the counter
  500.  
  501.         Mov    DI,Offset FileBuffer    ; And the pointer
  502.  
  503.         Mov    CS:[BufferPtr],DI    ; Save the pointer
  504.  
  505.         Mov    CX,528 * 39        ; Will clear for 528 files
  506.  
  507.         Mov    AL,' '            ; With a blank
  508.  
  509.         Rep    Stosb            ; Clear it out
  510.  
  511.         Pop    CX            ; And get back register
  512.  
  513.  
  514.  
  515. NotTooManyFiles:Mov    CS:[WithinFileList],1    ; We're doing files now
  516.  
  517.         Mov    CS:[NowDoingFile],1    ; And a file in particular
  518.  
  519.         Inc    CS:[FileCounter]    ; So kick up this counter
  520.  
  521.  
  522.  
  523. NotLineBegin:    Cmp    CS:[NowDoingFile],1    ; See if doing files
  524.  
  525.         Je    StoreCharacters        ; If so, store the stuff
  526.  
  527.  
  528.  
  529. AllowTransfer:    Pop    ES            ; Pop all the registers
  530.  
  531.         Pop    DI
  532.  
  533.         Pop    SI
  534.  
  535.         Pop    CX
  536.  
  537.         Pop    AX
  538.  
  539.         PopF
  540.  
  541.  
  542.  
  543.         Jmp    SkipIntercept        ; And go to DOS for print
  544.  
  545.  
  546.  
  547. StoreCharacters:Mov    DI,CS:[BufferPtr]    ; Set destination
  548.  
  549.         Rep    Movsb            ; Move characters to buffer
  550.  
  551.         Mov    CS:[BufferPtr],DI    ; And save new pointer    
  552.  
  553.  
  554.  
  555. PopAndReturn:    Pop    ES            ; Pop all the registers
  556.  
  557.         Pop    DI
  558.  
  559.         Pop    SI
  560.  
  561.         Pop    CX
  562.  
  563.         Pop    AX
  564.  
  565.         PopF
  566.  
  567.  
  568.  
  569.         Mov    AX,CX            ; Set for COMMAND.COM
  570.  
  571.         Clc                ; No error here 
  572.  
  573.         Ret    2            ; Return with CY flag cleared
  574.  
  575.  
  576.  
  577. NewInterrupt21    EndP
  578.  
  579.  
  580.  
  581. ;    Sort Files
  582.  
  583. ;    ----------
  584.  
  585.  
  586.  
  587. SortAndList:    Push    BX            ; Push a bunch of registers
  588.  
  589.         Push    DX
  590.  
  591.         Push    SI
  592.  
  593.         Push    DS
  594.  
  595.  
  596.  
  597.         Push    CS            ; Push CS
  598.  
  599.         Pop    DS            ;    so we can set DS to it
  600.  
  601.         Assume    DS:CSEG            ; And inform the assembler
  602.  
  603.  
  604.  
  605.         Mov    DI,Offset FileBuffer    ; This is the beginning
  606.  
  607.         Mov    CX,[FileCounter]    ; Number of files to sort
  608.  
  609.         Dec    CX            ; Loop needs one less than that 
  610.  
  611.         Jcxz    AllSorted        ; But zero means only one file
  612.  
  613.  
  614.  
  615. SortLoop1:    Push    CX            ; Save the file counter
  616.  
  617.         Mov    SI,DI            ; Set source to destination
  618.  
  619.  
  620.  
  621. SortLoop2:    Add    SI,39            ; Set source to next file
  622.  
  623.  
  624.  
  625.         Push    CX            ; Save the counter,
  626.  
  627.         Push    SI            ;    compare source,
  628.  
  629.         Push    DI            ;    and compare destination
  630.  
  631.  
  632.  
  633.         Mov    CX,39            ; 39 characters to compare
  634.  
  635.         Repz    Cmpsb            ; Do the compare
  636.  
  637.         Jae    NoSwitch        ; Jump if already in order
  638.  
  639.  
  640.  
  641.         Pop    DI            ; Get back these registers
  642.  
  643.         Pop    SI
  644.  
  645.  
  646.  
  647.         Push    SI            ; And push them again for move
  648.  
  649.         Push    DI
  650.  
  651.  
  652.  
  653.         Mov    CX,39            ; 39 characters
  654.  
  655. SwitchLoop:    Mov    AL,ES:[DI]        ; Character from destination 
  656.  
  657.         Movsb                ; Source to destination
  658.  
  659.         Mov    DS:[SI - 1],AL        ; Character to source
  660.  
  661.         Loop    SwitchLoop        ; For the rest of the line
  662.  
  663.  
  664.  
  665. NoSwitch:    Pop    DI            ; Get back the registers
  666.  
  667.         Pop    SI
  668.  
  669.         Pop    CX
  670.  
  671.         Loop    SortLoop2        ; And loop for next file
  672.  
  673.  
  674.  
  675.         Pop    CX            ; Get back file counter 
  676.  
  677.         Add    DI,39            ; Compare with next file
  678.  
  679.         Loop    SortLoop1        ; And loop again
  680.  
  681.  
  682.  
  683. ;    Now Display Sorted Files
  684.  
  685. ;    ------------------------
  686.  
  687.  
  688.  
  689. AllSorted:    Mov    SI,Offset FileBuffer    ; This is the beginning
  690.  
  691.         Mov    CX,[FileCounter]    ; Number of files to list
  692.  
  693.         Inc    CX            ; In case CX is odd
  694.  
  695.         Shr    CX,1            ; CX now is number of lines
  696.  
  697.  
  698.  
  699. SetIncrement:    Mov    BX,24 * 39        ; Increment for double list
  700.  
  701.         Cmp    CX,24            ; But use it only if a full
  702.  
  703.         Jae    LineLoop        ;    screen is printed    
  704.  
  705.  
  706.  
  707.         Mov    AX,39            ; Otherwise find increment
  708.  
  709.         Mul    CX            ;    by multiplying CX by 39
  710.  
  711.         Mov    BX,AX            ; And make that the increment
  712.  
  713.  
  714.  
  715. LineLoop:    Call    PrintFile        ; Print the first column file
  716.  
  717.         Mov    AL,' '            ; Skip one space
  718.  
  719.         Call    PrintChar        ;    by printing blank
  720.  
  721.         Mov    AL,179            ; Put a line down the middle
  722.  
  723.         Call    PrintChar
  724.  
  725.         Mov    AL,' '            ; Skip another space
  726.  
  727.         Call    PrintChar
  728.  
  729.  
  730.  
  731.         Add    SI,BX            ; Bump up source by increment
  732.  
  733.         Sub    SI,39             ; But kick down by 39
  734.  
  735.  
  736.  
  737.         Call    PrintFile        ; Print the second column file
  738.  
  739.         Call    CRLF            ; And terminate line
  740.  
  741.  
  742.  
  743.         Sub    SI,BX            ; Bring pointer back down
  744.  
  745.  
  746.  
  747.         Inc    [LineCounter]        ; One more line completed
  748.  
  749.         Cmp    [LineCounter],24    ; Have we done whole screen?
  750.  
  751.         Jz    PauseAtEnd        ; If so, gotta pause now
  752.  
  753.  
  754.  
  755.         Loop    LineLoop        ; Otherwise just loop
  756.  
  757.         Jmp    Short AllFinished    ; And jump out when done
  758.  
  759.  
  760.  
  761. PauseAtEnd:    Mov    [LineCounter],0        ; Reset the counter
  762.  
  763.         Add    SI,BX            ; Go to next file
  764.  
  765.  
  766.  
  767.         Push    BX            ; Save these registers
  768.  
  769.         Push    CX
  770.  
  771.         Mov    DX,Offset PauseMessage    ; Test to print
  772.  
  773.         Mov    CX,Offset PauseMsgEnd - Offset PauseMessage
  774.  
  775.                         ; Number of characters
  776.  
  777.         Mov    BX,2            ; Standard ERROR Output
  778.  
  779.         Mov    AH,40h            ; Display to screen
  780.  
  781.         Int    21h            ; By calling DOS 
  782.  
  783.         Pop    CX            ; Retrieve pushed registers 
  784.  
  785.         Pop    BX
  786.  
  787.  
  788.  
  789.         Mov    AH,8            ; Wait for character
  790.  
  791.         Int    21h            ; Through DOS call
  792.  
  793.  
  794.  
  795.         Call    CRLF            ; Go to next line 
  796.  
  797.  
  798.  
  799.         Loop    SetIncrement        ; And recalculate increment
  800.  
  801.  
  802.  
  803. AllFinished:    Pop    DS            ; Done with subroutine
  804.  
  805.         Pop    SI
  806.  
  807.         Pop    DX
  808.  
  809.         Pop    BX
  810.  
  811.         Ret                ; So return to caller
  812.  
  813.  
  814.  
  815. ;    Display Routines
  816.  
  817. ;    ----------------
  818.  
  819.  
  820.  
  821. PrintChar:    Mov    DL,AL            ; Print character in AL
  822.  
  823.         Mov    AH,2            ; By simple DOS call
  824.  
  825.         Int    21h
  826.  
  827.         Ret                ; And return
  828.  
  829.  
  830.  
  831. CRLF:        Mov    AL,13            ; Print a carriage return
  832.  
  833.         Call    PrintChar
  834.  
  835.         Mov    AL,10            ; And a line feed
  836.  
  837.         Call    PrintChar
  838.  
  839.         Ret                ; And return
  840.  
  841.  
  842.  
  843. PrintString:    Lodsb                ; Get character from SI
  844.  
  845.         Call    PrintChar        ; Print it
  846.  
  847.         Loop    PrintString        ; Do that CX times
  848.  
  849.         Ret                ; And return
  850.  
  851.  
  852.  
  853. PrintFile:    Push    CX            ; Save the counter
  854.  
  855.         Mov    CX,32            ; Bytes for Name, Size, & Date
  856.  
  857.         Call    PrintString        ; Print it    
  858.  
  859.         Inc    SI            ; Skip one space before time
  860.  
  861.         Mov    CX,6            ; Bytes for Time
  862.  
  863.         Call    PrintString        ; It's a print!
  864.  
  865.         Pop    CX        
  866.  
  867.         Ret                ; And return
  868.  
  869.  
  870.  
  871. FileBuffer    Label    Byte            ; Points to end of code
  872.  
  873.  
  874.  
  875. CSEG        EndS                ; End of segment
  876.  
  877.  
  878.  
  879.         End    Entry            ; Denotes entry point
  880.  
  881.